home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / samdu220.zip / HANDLEST.C < prev    next >
Text File  |  1993-04-01  |  29KB  |  548 lines

  1. /*********************************************************************/
  2. /*                                                                   */
  3. /*    Name:    HANDLEST.C                                            */
  4. /*                                                                   */
  5. /*    Copyright (c) Stewart A. Berman 1992, All rights reserved      */
  6. /*                                                                   */
  7. /*********************************************************************/
  8. #pragma warning (disable:4001)
  9. #include <Windows.h>
  10. #pragma warning (default:4001)
  11.  
  12. #include <String.h>
  13.  
  14. #include "HandleSt.h"
  15. #include "IOStatus.h"
  16.  
  17. #ifdef DEBUG
  18. #include "DebugOut.h"
  19. #endif
  20.  
  21. #ifdef _cplusplus
  22. extern "C" {
  23. #endif /* _cplusplus */
  24.  
  25. BOOL bTimerInterval ;
  26.  
  27. int  FAR PASCAL HandleStatus ( UINT nStatus1, UINT nStatus2, UINT nParam1, UINT nParam2, LONG lParam1, LONG lParam2 )
  28. {
  29. /********************************************************************/
  30. /*                                                                  */
  31. /* This is the callback function for disk activity status           */
  32. /*                                                                  */
  33. /* 1. Determine the type of callback (based on nStatus1)            */
  34. /*                                                                  */
  35. /* nStatus                  Action                                  */
  36. /* -------                  ------                                  */
  37. /* STATUS1_INIT              Save hWnd and hInstance                */
  38. /* STATUS1_START             Send USR_ACTIVE message                */
  39. /* STATUS1_BOOT_SECTOR       Send USR_ACTIVE message                */
  40. /* STATUS1_DIRECTORY         Send USR_ACTIVE message                */
  41. /* STATUS1_FAT               Send USR_ACTIVE message                */
  42. /* STATUS1_SYSTEM_FILE       Send USR_ACTIVE message                */
  43. /* STATUS1_CYLINDER          Send USR_UPDATE message                */
  44. /* STATUS1_HEAD              Ignore                                 */
  45. /* STATUS1_END               Beep and/or Flash if option selected   */
  46. /* STATUS1_ERROR             Error type dependent                   */
  47. /*                                                                  */
  48. /********************************************************************/
  49.  
  50.     static BOOL bFlash = FALSE ;
  51.     static BOOL bSound = FALSE ;
  52.  
  53.     static HINSTANCE hInstance = NULL ;
  54.  
  55.     static HWND      hWnd      = NULL;
  56.  
  57.     static UINT nTimerInterval ;
  58.  
  59.     static TIMERPROC lpfnSABDUTimerFunc ;
  60.  
  61.     char czBuffer1[512] ;
  62.     char czBuffer2[512] ;
  63.  
  64.     char czIconMessage[512] ;
  65.     char czNormalMessage[512] ;
  66.  
  67.     STMESSAGE stMessage ;
  68.     STMESSAGE far *lpstMessage ;
  69.  
  70.     MSG msg ;
  71.  
  72. /********************************************************************/
  73. /*                                                                  */
  74. /* We want to be a well behaved Windows application so we need to   */
  75. /* let go of the CPU and let other applications get some work done. */
  76. /*                                                                  */
  77. /********************************************************************/
  78.  
  79.     while ( PeekMessage ( &msg, NULL, NULL, NULL, PM_REMOVE ) )
  80.           {
  81.           TranslateMessage ( &msg ) ;
  82.           DispatchMessage  ( &msg ) ;
  83.           }
  84.  
  85. /********************************************************************/
  86. /*                                                                  */
  87. /* The following is a multilevel switch for processing callback     */
  88. /* requests.                                                        */
  89. /*                                                                  */
  90. /* The first level is seperates the major areas.  Most of them are  */
  91. /* normal operation and are provided so the application can keep    */
  92. /* the user informed on the progress of long running tasks.         */
  93. /* Most of the first level messages are sent via SendMessage.       */
  94. /* The response is passed back to the routine issuing the callback  */
  95. /* requests.  This allows the application to stop a long running    */
  96. /* process by returning an IDCANCEL in response to the SendMessage  */
  97. /* request.                                                         */
  98. /*                                                                  */
  99. /* The second level is used to seperate the various types of error  */
  100. /* notifications.  Some of them prompt the user for a decision as   */
  101. /* to whether or not a retry should be attempted.  Others simply    */
  102. /* notify the user of a problem.                                    */
  103. /*                                                                  */
  104. /* The general method used to kept the user informed is to update   */
  105. /* two messages used by our WM_PAINT routine.  One is used when the */
  106. /* application is running in Iconic state and the other is for when */
  107. /* it is not running in Iconic state.  The messages are built here  */
  108. /* and passed in a structure via a SendMessage call to a routine    */
  109. /* that stores them where the WM_PAINT routine can access them.     */
  110. /* This maintains complete independence between this routine and    */
  111. /* the WM_PAINT routine.                                            */
  112. /*                                                                  */
  113. /********************************************************************/
  114.  
  115. #ifdef DEBUG
  116.     if ( pCDebugOut!=NULL )
  117.        {
  118.        wsprintf (
  119.                  (LPSTR)DebugOutczDebugBuffer(),
  120.                  (LPSTR)"Status1: %4.4X\n"
  121.                         "Status2: %4.4X\n"
  122.                         "nParam1: %4.4X\n"
  123.                         "nParam2: %4.4X\n"
  124.                         "lParam1: %8.8lX\n"
  125.                         "lParam2: %8.8lX",
  126.                  nStatus1,
  127.                  nStatus2,
  128.                  nParam1,
  129.                  nParam2,
  130.                  lParam1,
  131.                  lParam2
  132.                 ) ;
  133.        DebugOutOutputIf ( 0x00000001, DebugOutczDebugBuffer(), "HandleStatus", MB_ICONINFORMATION|MB_OK ) ;
  134.        }
  135. #endif
  136.  
  137.     switch ( nStatus1 )
  138.        {
  139.        case STATUS1_INIT:              /* User is passing hWnd, hInstance, and timer controls */
  140.           {
  141.           hWnd      = (HWND)nParam1 ;
  142.           hInstance = (HINSTANCE)nParam2 ;
  143.           nTimerInterval = LOWORD ( lParam1 ) ;
  144.           bFlash = HIWORD ( lParam2 ) ;
  145.           bSound = LOWORD ( lParam2 ) ;
  146.           return ( FALSE ) ;
  147.           break ;
  148.           }
  149.        case STATUS1_START:             /* We are starting a long running process */
  150.           {
  151.           wsprintf ( (LPSTR)czIconMessage,   (LPCSTR)"%2.2d  %3.2d%%", 0, 0 ) ;
  152.           stMessage.pIconMessage = czIconMessage ;
  153.           wsprintf ( (LPSTR)czNormalMessage, (LPCSTR)"Cylinder %2.2d (%3.2d%%)", 0, 0 ) ;
  154.           stMessage.pNormalMessage = czNormalMessage ;
  155.           stMessage.nPercentageToColor = 0 ;
  156.           lpstMessage = (STMESSAGE far *) &stMessage ;
  157.           return ( LOWORD (SendMessage ( hWnd, USR_ACTIVE, 0, (LONG)lpstMessage ) ) ) ;
  158.           break ;
  159.           }
  160.        case STATUS1_BOOT_SECTOR:       /* We are installing a new boot sector */
  161.           {
  162.           _fstrcpy ( (LPSTR)czIconMessage,   (LPCSTR)"Boot" ) ;
  163.           stMessage.pIconMessage = czIconMessage ;
  164.           _fstrcpy ( (LPSTR)czNormalMessage, (LPCSTR)"Installing Boot Sector" ) ;
  165.           stMessage.pNormalMessage = czNormalMessage ;
  166.           stMessage.nPercentageToColor = 100 ;
  167.           lpstMessage = (STMESSAGE far *) &stMessage ;
  168.           return ( LOWORD ( SendMessage ( hWnd, USR_ACTIVE, 0, (LONG)lpstMessage ) ) ) ;
  169.           break ;
  170.           }
  171.        case STATUS1_DIRECTORY:         /* We are building a diskette directory */
  172.           {
  173.           _fstrcpy ( (LPSTR)czIconMessage,   (LPCSTR)"DIR" ) ;
  174.           stMessage.pIconMessage = czIconMessage ;
  175.           _fstrcpy ( (LPSTR)czNormalMessage, (LPCSTR)"Creating Directory" ) ;
  176.           stMessage.pNormalMessage = czNormalMessage ;
  177.           stMessage.nPercentageToColor = 100 ;
  178.           lpstMessage = (STMESSAGE far *) &stMessage ;
  179.           return ( LOWORD ( SendMessage ( hWnd, USR_ACTIVE, 0, (LONG)lpstMessage ) ) ) ;
  180.           break ;
  181.           }
  182.        case STATUS1_FAT:               /* We are building a diskette File Allocation Table */
  183.           {
  184.           _fstrcpy ( (LPSTR)czIconMessage,   (LPCSTR)"FAT" ) ;
  185.           stMessage.pIconMessage = czIconMessage ;
  186.           _fstrcpy ( (LPSTR)czNormalMessage, (LPCSTR)"Creating File Allocation Table" ) ;
  187.           stMessage.pNormalMessage = czNormalMessage ;
  188.           stMessage.nPercentageToColor = 100 ;
  189.           lpstMessage = (STMESSAGE far *) &stMessage ;
  190.           return ( LOWORD ( SendMessage ( hWnd, USR_ACTIVE, 0, (LONG)lpstMessage ) ) ) ;
  191.           break ;
  192.           }
  193.        case STATUS1_SYSTEM_FILE:       /* We are copying a system file */
  194.           {
  195.           _fstrcpy ( (LPSTR)czIconMessage, (LPSTR)(_fstrrchr ( (LPCSTR)lParam1, '\\' ) + 1 ) ) ;
  196.           *(strrchr( czIconMessage, '.' )) = '\n' ;
  197.           stMessage.pIconMessage = czIconMessage ;
  198.           _fstrcpy ( (LPSTR)czNormalMessage, (LPCSTR)"Copying System File: " ) ;
  199.           _fstrcat ( (LPSTR)czNormalMessage, (LPCSTR)lParam1 ) ;
  200.           stMessage.pNormalMessage = czNormalMessage ;
  201.           stMessage.nPercentageToColor = 100 ;
  202.           lpstMessage = (STMESSAGE far *) &stMessage ;
  203.           return ( LOWORD ( SendMessage ( hWnd, USR_ACTIVE, 0, (LONG)lpstMessage ) ) ) ;
  204.           break ;
  205.           }
  206.        case STATUS1_CYLINDER:          /* We are about to start a new cylinder */
  207.           {
  208.           /**********************************************************/
  209.           /*                                                        */
  210.           /* We will check to see if the user has specified a       */
  211.           /* minimum amount of time to wait between cylinders.  If  */
  212.           /* they have we will start a timer and wait for it to     */
  213.           /* complete before going on.                              */
  214.           /*                                                        */
  215.           /* Note that the PeekMessage loop is needed for two       */
  216.           /* reasons.  It is the way we can release control so      */
  217.           /* other applications can run and it is needed so our     */
  218.           /* own WM_TIMER message can be processed.                 */
  219.           /*                                                        */
  220.           /**********************************************************/
  221.           bTimerInterval = FALSE ;
  222.           lpfnSABDUTimerFunc = MakeProcInstance ( (FARPROC)SABDUTimerFunc, hInstance ) ;
  223.           SetTimer ( hWnd, TIMER_INTERVAL, nTimerInterval, lpfnSABDUTimerFunc ) ;
  224.           while ( !bTimerInterval )
  225.              {
  226.              while ( PeekMessage ( &msg, NULL, NULL, NULL, PM_REMOVE ) )
  227.                    {
  228.                    TranslateMessage ( &msg ) ;
  229.                    DispatchMessage  ( &msg ) ;
  230.                    }
  231.              }
  232.           KillTimer ( hWnd, TIMER_INTERVAL ) ;
  233.           FreeProcInstance ( lpfnSABDUTimerFunc ) ;
  234.           wsprintf ( (LPSTR)czIconMessage,   (LPCSTR)"%2.2d  %3.2d%%",   nParam1, nParam2 ) ;
  235.           stMessage.pIconMessage = czIconMessage ;
  236.           wsprintf ( (LPSTR)czNormalMessage, (LPCSTR)"Cylinder %2.2d (%3.2d%%)", nParam1, nParam2 ) ;
  237.           stMessage.pNormalMessage = czNormalMessage ;
  238.           stMessage.nPercentageToColor = nParam2 ;
  239.           lpstMessage = (STMESSAGE far *) &stMessage ;
  240.           return ( LOWORD ( SendMessage ( hWnd, USR_UPDATE, 0, (LONG)lpstMessage ) ) ) ;
  241.           break ;
  242.           }
  243.        case STATUS1_HEAD:              /* We are about to start a new head */
  244.           {
  245.           break ;
  246.           }
  247.        case STATUS1_END:               /* We have completed a long running task */
  248.           {
  249.           if ( (bFlash) && (hWnd!=GetActiveWindow()))
  250.              {
  251.              lpfnSABDUTimerFunc = MakeProcInstance ( (FARPROC)SABDUTimerFunc, hInstance ) ;
  252.              SetTimer ( hWnd, TIMER_INTERVAL, 1000, lpfnSABDUTimerFunc ) ;
  253.              while ( hWnd != GetActiveWindow() )
  254.                 {
  255.                 FlashWindow ( hWnd, TRUE ) ;
  256.                 if (bSound) MessageBeep ( 0 ) ;
  257.                 bTimerInterval = FALSE ;
  258.                 while ( !bTimerInterval )
  259.                    {
  260.                    while ( PeekMessage ( &msg, NULL, NULL, NULL, PM_REMOVE ) )
  261.                          {
  262.                          TranslateMessage ( &msg ) ;
  263.                          DispatchMessage  ( &msg ) ;
  264.                          }
  265.                    }
  266.                 }
  267.              FlashWindow ( hWnd, FALSE ) ;
  268.              KillTimer ( hWnd, TIMER_INTERVAL ) ;
  269.              FreeProcInstance ( lpfnSABDUTimerFunc ) ;
  270.              }
  271.           else
  272.              {
  273.              if ( bSound ) MessageBeep ( 0 ) ;
  274.              }
  275.           PostMessage ( hWnd, USR_INACTIVE, 0, 0L ) ;
  276.           break ;
  277.           }
  278.        case STATUS1_ERROR:             /* We have an error that needs to be dealt with */
  279.           {
  280.           switch (nStatus2)
  281.              {
  282.              case STATUS2_FILE:             /* It is a file error */
  283.                 {
  284.                 /****************************************************/
  285.                 /*                                                  */
  286.                 /* All file errors are unrecoverable.  That is the  */
  287.                 /* file operation will terminate and control will   */
  288.                 /* return to the main routine.                      */
  289.                 /*                                                  */
  290.                 /* The nParam1 indicates the type of file error.    */
  291.                 /* A message is built for that particular error.    */
  292.                 /* At the end of the switch statement a MessageBox  */
  293.                 /* call is used to display the message              */
  294.                 /*                                                  */
  295.                 /****************************************************/
  296.                 switch ( nParam1 )
  297.                    {
  298.                    case STATUS3_OPEN_FAIL:            /* We could not open the file */
  299.                       {
  300.                       wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"Open failed for: %s", (LPCSTR)lParam1 ) ;
  301.                       break ;
  302.                       }
  303.                    case STATUS3_OPEN_FILE_IO_ERROR:   /* We had an I/O error */
  304.                       {
  305.                       wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"File I/O Error: %s", (LPCSTR)lParam1 ) ;
  306.                       break ;
  307.                       }
  308.                    case STATUS3_OPEN_INPUT_BAD:       /* The file is not one of ours */
  309.                       {
  310.                       wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"Input file ID is invalid: %s", (LPCSTR)lParam1 ) ;
  311.                       break ;
  312.                       }
  313.                    case STATUS3_OPEN_FLAGS_BAD:       /* We don't support a flagged option */
  314.                       {
  315.                       wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"Input file has unsupport option: %4.4X", nParam2 ) ;
  316.                       break ;
  317.                       }
  318.                    case STATUS3_OPEN_NOT_SUPPORTED:   /* We don't support the device type */
  319.                       {
  320.                       wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"Device type, %4.4X, is not supported", nParam2 ) ;
  321.                       break ;
  322.                       }
  323.                    default:                           /* We don't know what went wrong */
  324.                       {
  325.                       czBuffer1[0] = '\0' ;
  326.                       break ;
  327.                       }
  328.                    }
  329.                 GetWindowText ( hWnd, czBuffer1, 511) ;
  330.                 return (MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONEXCLAMATION|MB_OK )) ;
  331.                 break ;
  332.                 }
  333.              case STATUS2_READ:             /* It was a read error */
  334.                 {
  335.                 /****************************************************/
  336.                 /*                                                  */
  337.                 /* We will tell the user about the error and let    */
  338.                 /* them decided if we should retry.  The response   */
  339.                 /* from the user will be returned to the routine    */
  340.                 /* that issued the callback address.  Hopefully,    */
  341.                 /* it will know what to do with it.                 */
  342.                 /*                                                  */
  343.                 /****************************************************/
  344.                 wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"%s Error at Cylinder %d, Head %d", (LPCSTR)"Read", nParam1, nParam2 ) ;
  345.                 _fstrcat ( czBuffer2, "\nPossible causes:" ) ;
  346.                 _fstrcat ( czBuffer2, "\nDiskette is not positioned properly in drive" ) ;
  347.                 _fstrcat ( czBuffer2, "\nDiskette drive door is not closed" ) ;
  348.                 _fstrcat ( czBuffer2, "\nDiskette is not formatted" ) ;
  349.                 GetWindowText ( hWnd, czBuffer1, 255 ) ;
  350.                 return ( MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONSTOP|MB_RETRYCANCEL ) ) ;
  351.                 break ;
  352.                 }
  353.              case STATUS2_WRITE:            /* It was a write error */
  354.                 {
  355.                 /****************************************************/
  356.                 /*                                                  */
  357.                 /* We will tell the user about the error and let    */
  358.                 /* them decided if we should retry.  The response   */
  359.                 /* from the user will be returned to the routine    */
  360.                 /* that issued the callback address.  Hopefully,    */
  361.                 /* it will know what to do with it.                 */
  362.                 /*                                                  */
  363.                 /****************************************************/
  364.                 wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"%s Error at Cylinder %d, Head %d", (LPCSTR)"Write", nParam1, nParam2 ) ;
  365.                 _fstrcat ( czBuffer2, "\nPossible causes:" ) ;
  366.                 _fstrcat ( czBuffer2, "\nDiskette is not positioned properly in drive" ) ;
  367.                 _fstrcat ( czBuffer2, "\nDiskette drive door is not closed" ) ;
  368.                 _fstrcat ( czBuffer2, "\nDiskette has write protect tab" ) ;
  369.                 _fstrcat ( czBuffer2, "\nDiskette is not formatted" ) ;
  370.                 GetWindowText ( hWnd, czBuffer1, 255 ) ;
  371.                 return ( MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONSTOP|MB_RETRYCANCEL ) ) ;
  372.                 break ;
  373.                 }
  374.              case STATUS2_FORMAT:           /* It was a format error */
  375.                 {
  376.                 /****************************************************/
  377.                 /*                                                  */
  378.                 /* We will tell the user about the error and let    */
  379.                 /* them decided if we should retry.  The response   */
  380.                 /* from the user will be returned to the routine    */
  381.                 /* that issued the callback address.  Hopefully,    */
  382.                 /* it will know what to do with it.                 */
  383.                 /*                                                  */
  384.                 /****************************************************/
  385.                 wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"%s Error at Cylinder %d, Head %d", (LPCSTR)"Format", nParam1, nParam2 ) ;
  386.                 _fstrcat ( czBuffer2, "\nPossible causes:" ) ;
  387.                 _fstrcat ( czBuffer2, "\nDiskette is not positioned properly in drive" ) ;
  388.                 _fstrcat ( czBuffer2, "\nDiskette drive door is not closed" ) ;
  389.                 _fstrcat ( czBuffer2, "\nDiskette has write protect tab" ) ;
  390.                 GetWindowText ( hWnd, czBuffer1, 255 ) ;
  391.                 return ( MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONSTOP|MB_ABORTRETRYIGNORE ) ) ;
  392.                 break ;
  393.                 }
  394.              case STATUS2_FILE_READ:        /* It was a file read error */
  395.              case STATUS2_FILE_WRITE:       /* It was a file write error */
  396.                 {
  397.                 /****************************************************/
  398.                 /*                                                  */
  399.                 /* We will tell the user about the error and let    */
  400.                 /* them decided if we should retry.  The response   */
  401.                 /* from the user will be returned to the routine    */
  402.                 /* that issued the callback address.  Hopefully,    */
  403.                 /* it will know what to do with it.                 */
  404.                 /*                                                  */
  405.                 /****************************************************/
  406.                 wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"File I/O Error: %s", (LPCSTR)lParam1 ) ;
  407.                 GetWindowText ( hWnd, czBuffer1, 255 ) ;
  408.                 return ( MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONSTOP|MB_RETRYCANCEL ) ) ;
  409.                 break ;
  410.                 }
  411.              case STATUS2_DISK_SPACE:       /* We don't have enough disk space */
  412.                 {
  413.                 wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"Drive does not have enough space available for file\n%10ld Bytes Required\n%10ld Bytes Available", lParam1, lParam2 ) ;
  414.                 GetWindowText ( hWnd, czBuffer2, 511) ;
  415.                 return (MessageBox ( hWnd, czBuffer1, czBuffer2, MB_ICONEXCLAMATION|MB_OK )) ;
  416.                 break ;
  417.                 }
  418.              case STATUS2_HEAD:             /* We had an I/O error at the track (head) level */
  419.                 {
  420.                 wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"%s Error at Cylinder %d, Head %d", (LPSTR)"", nParam1, nParam2 ) ;
  421.                 _fstrcat ( czBuffer2, "\nPossible causes:" ) ;
  422.                 _fstrcat ( czBuffer2, "\nDiskette is not positioned properly in drive" ) ;
  423.                 _fstrcat ( czBuffer2, "\nDiskette drive door is not closed" ) ;
  424.                 GetWindowText ( hWnd, czBuffer1, 511) ;
  425.                 return (MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONSTOP|MB_RETRYCANCEL )) ;
  426.                 break ;
  427.                 }
  428.              case STATUS2_MEMORY:           /* We don't have enough memory */
  429.                 {
  430.                 GetWindowText ( hWnd, czBuffer1, 511) ;
  431.                 return (MessageBox ( hWnd, "Unable to Allocate Memory", czBuffer1, MB_ICONEXCLAMATION|MB_OK )) ;
  432.                 break ;
  433.                 }
  434.              case STATUS2_SYSTEM:           /* We have a bad sector in the system are of the diskette */
  435.              case STATUS2_FAT:              /* We have a bad sector in the File Allocation Table area of a diskette */
  436.              case STATUS2_DIRECTORY:        /* We have a bad sector in the root directory area of a diskette */
  437.                 {
  438.                 GetWindowText ( hWnd, czBuffer1, 511) ;
  439.                 return (MessageBox ( hWnd, "Bad Sector in System Area - Disk is unusable", czBuffer1, MB_ICONEXCLAMATION|MB_OK )) ;
  440.                 break ;
  441.                 }
  442.              case STATUS2_BOOT_SECTOR:      /* We couldn't write out a boot sector */
  443.                 {
  444.                 wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"Unable to Write the Boot Sector on the %c Drive", ' ' ) ;
  445.                 _fstrcat ( czBuffer2, "\nPossible causes:" ) ;
  446.                 _fstrcat ( czBuffer2, "\nDiskette is not positioned properly in drive" ) ;
  447.                 _fstrcat ( czBuffer2, "\nDiskette drive door is not closed" ) ;
  448.                 _fstrcat ( czBuffer2, "\nDiskette has write protect tab" ) ;
  449.                 _fstrcat ( czBuffer2, "\nDiskette is not formatted" ) ;
  450.                 GetWindowText ( hWnd, czBuffer1, 255 ) ;
  451.                 return ( MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONSTOP|MB_RETRYCANCEL ) ) ;
  452.                 break ;
  453.                 }
  454.              case STATUS2_SYSTEM_FILE_MISSING:   /* We couldn't find one of the system files */
  455.                 {
  456.                 GetWindowText ( hWnd, czBuffer1, 511) ;
  457.                 return (MessageBox ( hWnd, "Unable to Find System Files", czBuffer1, MB_ICONEXCLAMATION|MB_OK )) ;
  458.                 break ;
  459.                 }
  460.              case STATUS2_SYSTEM_FILE_OPEN: /* We couldn't open one of the system files */
  461.                 {
  462.                 wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"Unable to Open System File: %s", (LPCSTR)lParam1 ) ;
  463.                 GetWindowText ( hWnd, czBuffer1, 511) ;
  464.                 return (MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONEXCLAMATION|MB_OK )) ;
  465.                 break ;
  466.                 }
  467.              case STATUS2_COMPARE:          /* We were doing a compare and something didn't */
  468.                 {
  469.                 _fstrcpy ( czBuffer1, "Difference found at Cylinder %d, head %d" ) ;
  470.                 _fstrcat ( czBuffer1, "\nContinue with %s?" ) ;
  471.                 wsprintf ( (LPSTR)czBuffer2, (LPCSTR)czBuffer1, nParam1, nParam2, (LPCSTR)"Compare" ) ;
  472.                 GetWindowText ( hWnd, czBuffer1, 511) ;
  473.                 return ( MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONSTOP|MB_YESNO ) ) ;
  474.                 break ;
  475.                 }
  476.              case STATUS2_DPT:              /* It was a DPT error */
  477.                 {
  478.                 /****************************************************/
  479.                 /*                                                  */
  480.                 /* We will tell the user about the error and let    */
  481.                 /* them decided if we should retry.  The response   */
  482.                 /* from the user will be returned to the routine    */
  483.                 /* that issued the callback address.  Hopefully,    */
  484.                 /* it will know what to do with it.                 */
  485.                 /*                                                  */
  486.                 /****************************************************/
  487.                 wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"Unable to Read Device Parameter Table of Diskette in Drive %c:", nParam1 ) ;
  488.                 _fstrcat ( czBuffer2, "\nPossible causes:" ) ;
  489.                 _fstrcat ( czBuffer2, "\nDiskette is not positioned properly in drive" ) ;
  490.                 _fstrcat ( czBuffer2, "\nDiskette drive door is not closed" ) ;
  491.                 _fstrcat ( czBuffer2, "\nDiskette is not formatted" ) ;
  492.                 GetWindowText ( hWnd, czBuffer1, 255 ) ;
  493.                 return ( MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONEXCLAMATION|MB_OK ) ) ;
  494.                 break ;
  495.                 }
  496.              case STATUS2_SECTORS:          /* Target diskette does not have the same sectors/track as the source image */
  497.                 {
  498.                 /****************************************************/
  499.                 /*                                                  */
  500.                 /* We will tell the user about the error and let    */
  501.                 /* them decided if we should continue. The response */
  502.                 /* from the user will be returned to the routine    */
  503.                 /* that issued the callback address.  Hopefully,    */
  504.                 /* it will know what to do with it.                 */
  505.                 /*                                                  */
  506.                 /****************************************************/
  507.                 _fstrcpy ( czBuffer2, "The source image has a different structure than the target diskette:\n" ) ;
  508.                 wsprintf ( (LPSTR)czBuffer1, (LPCSTR)"%3.3u Sectors per track and %3.3u Cylinders in target diskette\n%3.3u Sectors per track and %3.3u Cylinders in source image",
  509.                                              nParam1, LOWORD ( lParam1 ), nParam2, LOWORD ( lParam2 ) ) ;
  510.                 _fstrcat ( czBuffer2, czBuffer1 ) ;
  511.                 _fstrcat ( czBuffer2, "\nPress OK to continue or Cancel to stop" ) ;
  512.                 GetWindowText ( hWnd, czBuffer1, 255 ) ;
  513.                 return ( MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONEXCLAMATION|MB_OKCANCEL ) ) ;
  514.                 break ;
  515.                 }
  516.              default:                       /* We are confused */
  517.                 {
  518.                 break ;
  519.                 }
  520.              }
  521.           break ;
  522.           }
  523.        default:                        /* We are confused */
  524.           {
  525.           break ;
  526.           }
  527.        }
  528.  
  529.     return ( TRUE ) ;                  /* We are confused but the truth will stop most things from continuing to go wrong. */
  530. }
  531.  
  532. int  FAR PASCAL SABDUTimerFunc ( HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime )
  533. {
  534.     /* Kill unreferenced formal parameter warnings */
  535.     if (hWnd) ;
  536.     if (nMsg) ;
  537.     if (nIDEvent) ;
  538.     if (dwTime) ;
  539.  
  540.     bTimerInterval = TRUE ;
  541.     return ( FALSE ) ;
  542. }
  543.  
  544. #ifdef _cplusplus
  545.            }
  546. #endif /* _cplusplus */
  547.  
  548.